﻿using BitButterECS.Event;
using BitButterECS.Event.EventArgs;
using System;
using System.Collections.Generic;

namespace BitButterECS.Entity
{
    public class EntityManager
    {
        EntityManager() { }
        
        public static EntityManager Instance => Nested.instance;

        class Nested
        {
            static Nested() { }
            internal static readonly EntityManager instance = new EntityManager();
        }

        public BaseEntity this[int index]
        {
            get
            {
                if (EntityCollection.ContainsKey(index))
                {
                    return EntityCollection[index];
                }
                return null;
            }
        }

        public BaseEntity this[Type queryType]
        {
            get
            {
                if (GlobalEntityCollection.ContainsKey(queryType))
                {
                    return GlobalEntityCollection[queryType];
                }
                return null;
            }
        }

        public int AddEntity(BaseEntity entity)
        {
            if (!entity.IsManaged)
            {
                entity.ID = currentID;
                currentID += 1;

                EntityCollection.Add(entity.ID, entity);

                if (GlobalEntityAttribute.IsGlobalEntity(entity))
                {
                    if (!GlobalEntityCollection.ContainsKey(entity.GetType()))
                    {
                        GlobalEntityCollection.Add(entity.GetType(), entity);
                    }
                }

                AddEntityEvent.RaiseEvent(this, new AddEntityEventArgs());
                return entity.ID;
            }
            return -1;
        }

        public void RemoveEntity(BaseEntity entity)
        {
            if (entity.IsManaged)
            {
                EntityCollection.Remove(entity.ID);
                entity.ID = -1;

                if (GlobalEntityAttribute.IsGlobalEntity(entity))
                {
                    if (GlobalEntityCollection.ContainsKey(entity.GetType()))
                    {
                        GlobalEntityCollection.Remove(entity.GetType());
                    }
                }

                RemoveEntityEvent.RaiseEvent(this, new RemoveEntityEventArgs());
            }
        }

        public bool HasEntity(int id)
        {
            return entityCollection != null ? entityCollection.ContainsKey(id) : false;
        }

        Dictionary<Type, BaseEntity> GlobalEntityCollection => globalEntityCollection ?? (globalEntityCollection = new Dictionary<Type, BaseEntity>());
        Dictionary<Type, BaseEntity> globalEntityCollection;

        Dictionary<int, BaseEntity> EntityCollection => entityCollection ?? (entityCollection = new Dictionary<int, BaseEntity>());
        Dictionary<int, BaseEntity> entityCollection;
        int currentID = 0;
    }
}
